/****************************************************************************
 *  QLyrics - A simple lyrics viewer.                                       *
 *  Copyright (C) 2008  hsys <hanshuiys@gmail.com>                          *
 *                                                                          *
 *  This program is free software; you can redistribute it and/or modify    *
 *  it under the terms of the GNU General Public License as published by    *
 *  the Free Software Foundation; either version 3 of the License, or       *
 *  (at your option) any later version.                                     *
 *                                                                          *
 *  This program is distributed in the hope that it will be useful,         *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
 *  GNU General Public License for more details.                            *
 *                                                                          *
 *  You should have received a copy of the GNU General Public License       *
 *  along with this program; if not, write to the Free Software Foundation, *
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA       *
 ****************************************************************************/

/****************************************************************************
 *  Support for TTPlayer protocol is based on Sevenever's python            *
 *  implementation, which is licenced under GNU GPLv2.                      *
 *  Thanks for his great work.                                              *
 *  Original website: http://code.google.com/p/ttplyrics/                   *
 ****************************************************************************/

#include "lyricsttprovider.h"
#include <QBuffer>
#include <QUrl>
#include <QHttp>
#include <QDomDocument>
#include <QDomElement>
#include <QTextCodec>

LyricsProvider* LyricsTTProvider::Builder::create(const Track& track, QObject* parent) const {
    LyricsTTProvider* inst = new LyricsTTProvider(parent);
    inst->m_track = track;
    return inst;
};

const QString& LyricsTTProvider::Builder::getProviderName() const {
    static QString name = LyricsTTProvider::tr("TTPlayer search");
    return name;
};

LyricsTTProvider::LyricsTTProvider(QObject* parent) : LyricsProvider(parent) {
    m_buffer = NULL;
};

QString LyricsTTProvider::encodeUrlQuery(const QByteArray& url) {
    QString encodedUrl;
    for (int i = 0; i < url.size(); i++) {
        encodedUrl = encodedUrl + QString("%1").arg((unsigned char)url.at(i), 2, 16, QChar('0'));
    };
    return encodedUrl;
};

void LyricsTTProvider::search() {
    if (m_buffer != NULL)
        delete m_buffer;
    m_buffer = new QBuffer(this);

    QTextCodec* codec = QTextCodec::codecForName("UTF-16");
    QString searchUrl = QString("/dll/lyricsvr.dll?sh?Artist=%1&Title=%2&Flags=0")
        .arg(encodeUrlQuery(codec->fromUnicode(m_track.artist.toLower().remove(' ')).remove(0, 2)))
        .arg(encodeUrlQuery(codec->fromUnicode(m_track.title.toLower().remove(' ')).remove(0, 2)));
    QHttpRequestHeader header("GET", searchUrl);
    header.setValue("Host", "lrcct2.ttplayer.com");
    header.setValue("User-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
    header.setValue("Connection", "close");
    m_http = new QHttp(this);
    m_http->setHost("lrcct2.ttplayer.com", QHttp::ConnectionModeHttp, 80);
    connect(m_http, SIGNAL(done(bool)), SLOT(slotSearchDone(bool)));

    // save the http request id for further use
    m_http->request(header, 0, m_buffer);
};

void LyricsTTProvider::slotSearchDone(bool error) {
    m_http->deleteLater();
    m_http = NULL;
    if (error) {
        m_status = NetworkError;
    } else {
        parseResult();
    };
    emit signalSearched();

    //m_http->deleteLater();
    //m_http = NULL;
};

int LyricsTTProvider::hashRequest(unsigned id, const QByteArray& str) {
    unsigned key1 = (((id & 0xff000000) == 0) ? (~id & 0x000000ff) : (id >> 24))
                  | (id & 0x0000ff00)
                  | (((id & 0x00ff0000) == 0) ? ((~id & 0x0000ff00) << 8) : (id & 0x00ff0000))
                  | (id << 24);
    
    unsigned key2 = 0;
    for (int i = str.length() - 1; i >= 0; i--) {
        key2 = (key2 << ((i % 2 == 0) ? 4 : 5)) + (str.at(i) + key2);
    };

    unsigned key3 = 0;
    for (int i = 0; i < str.length(); i++) {
        key3 = (key3 << ((i % 2 == 0) ? 3 : 4)) + (str.at(i) + key3);
    };

    key3 = (( ( ((key1 ^ key2) + (key3 | id)) *
                (unsigned long long)(key1 | key3))
              & 0x00000000ffffffff)
            * (key2 ^ id)) & 0x00000000ffffffff;
    return key3;
};

void LyricsTTProvider::parseResult() {
    QDomDocument doc;
   
    m_status = NotFound;
    QByteArray d = m_buffer->data();
    if (!doc.setContent(d))
        return;

    QDomElement root = doc.documentElement();
    bool ok;
    int id;
    SearchResult r;
    r.title = r.artist = r.album = r.url = r.album = r.preview = QString();
    for (QDomElement node = root.firstChildElement("lrc"); !node.isNull();
        node = node.nextSiblingElement("lrc")) {
        r.title = node.attribute("title");
        r.artist = node.attribute("artist");
        id = node.attribute("id").toInt(&ok);
        if (!ok)
            continue;
        r.url = QString("http://lrcct2.ttplayer.com/dll/lyricsvr.dll?dl?" \
            "Id=%1&Code=%2&uid=01&mac=%3")
            .arg(id)
            .arg(hashRequest(id, (r.artist + r.title).toUtf8()))
            .arg(qrand(), 12, 16, QChar('0')); // fake mac address
        if (!r.url.isEmpty())
            m_result.push_back(r);
    };
};

